package com.xpec.c4.service.common;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.xpec.c4.service.annotations.MessageType;
import com.xpec.c4.service.annotations.NoShareGroup;
import com.xpec.c4.service.annotations.ShareGroup;

/**
 * 消息号与处理类处理函数的映射配置
 * 
 * @author Bany
 * 
 * @since 2008-8-17 上午12:39:19
 * 
 */

@SuppressWarnings("rawtypes")
public class ModuleInfo {

	/**
	 * 消息号与处理类的映射
	 */
	private /*static*/ Map<Integer, Class> moduleClazzMapping = new HashMap<Integer, Class>();

	/**
	 * 消息号与处理方法的映射
	 */
	private /*static*/ Map<Integer, Method> moduleMethodMapping = new HashMap<Integer, Method>();

	/**
	 * 处理类列表
	 */
	private /*static*/ List<Class> classMapping = new ArrayList<Class>();

	/**
	 * 需要共享处理的方法，key为函数，value为存储比例
	 */
	private static final Map<Method, Integer> shareMethod = new HashMap<Method, Integer>();

	static {

		//initRegisterClass();
	}
	
	/**
	 * 
	 */
	public ModuleInfo(){
		initRegisterClass();
	}

	/**
	 * 
	 */
	private /* static*/ void initRegisterClass() {

		List<Class> dealClazz = classMapping;

		Collection<Class> registerClazz = moduleClazzMapping.values();

		// 遍历全部的注册类
		for (Class clazz : dealClazz) {
			// 如果已经有处理类，就不再处理。只处理新加的。
			if (!registerClazz.contains(clazz)) {
				Method[] methods = clazz.getMethods();
				// 遍历全部注册类的方法
				for (Method method : methods) 
				{
					MessageType type = method.getAnnotation(MessageType.class);
					if (type != null) {
						int typeCode = type.typeCode();
						// 把注册的方法登记
						registerModuleMethod(method, typeCode);
						// 把注册的代码及类进行关联
						registerModuleClazz(clazz, typeCode);
						// 把注册的需要共享处理的函数
						registerShareMethod(method);
					}
				}
			}
		}
	}

	/**
	 * 把注册的代码及类进行关联
	 * 
	 * @param clazz
	 * @param typeCode
	 */
	private /* static*/ void registerModuleClazz(Class clazz, int typeCode) {
		if(moduleClazzMapping.containsKey(typeCode))
		{
			System.out.print("<< CLASS REGISTER  ERROR >>" + typeCode + " is reduplicate!"
					+ moduleClazzMapping);
		}
		
		moduleClazzMapping.put(typeCode, clazz);
		
		/*同一個VM下，重覆開啟module並註冊同一組msg會報錯，修改成僅提醒但繼續執行
		
		if (!moduleClazzMapping.containsKey(typeCode)) {
			moduleClazzMapping.put(typeCode, clazz);
		} else {
			throw new ModuleInitException(typeCode + " is reduplicate!"
					+ moduleClazzMapping);
		}*/
	}

	/**
	 * 把注册的方法登记
	 * 
	 * @param method
	 * @param typeCode
	 */
	private /*static*/ void registerModuleMethod(Method method, int typeCode) {
		if(moduleClazzMapping.containsKey(typeCode))
		{
			System.out.print("<< MESSTYPE REGISTER  ERROR >>" + typeCode + " is reduplicate!"
					+ method);
		}
		
		method.setAccessible(true);
		moduleMethodMapping.put(typeCode, method);
		
		
		/*同一個VM下，重覆開啟module並註冊同一組msg會報錯，修改成僅提醒但繼續執行
		 * 
		 * if (!moduleClazzMapping.containsKey(typeCode)) {
			method.setAccessible(true);
			moduleMethodMapping.put(typeCode, method);
		} else {
			throw new ModuleInitException(typeCode + " is reduplicate!"
					+ method);
		}*/
	}
	
	/**
	 * 
	 * @param method
	 */
	private static void registerShareMethod(Method method) {
		// 如果没有检查过，则进行检查
		// 添加了@ ShareGroup，不管任何状态都共享
		if (method.isAnnotationPresent(ShareGroup.class)) {
			ShareGroup sg = method.getAnnotation(ShareGroup.class);
			shareMethod.put(method, sg.ratio());
		}
		// 添加了@ NoShareGroup
		// 函数名称有get或is开头，表示只用于获取数据，并不设置数据
		// 都不共享
		else if (!method.isAnnotationPresent(NoShareGroup.class)
				&& !method.getName().startsWith("get")
				&& !method.getName().startsWith("is")) {
			shareMethod.put(method, 0);
		}
	}

	/**
	 * 通过类型码，得到处理类
	 * 
	 * @param typeCode
	 * @return
	 */
	public /*static*/ Class getDealClazz(Integer typeCode) {
		return moduleClazzMapping.get(typeCode);
	}

	/**
	 * 通过类型码，得到处理函数
	 * 
	 * @param typeCode
	 * @return
	 */
	public /* static */ Method getDealMethod(Integer typeCode) {
		return moduleMethodMapping.get(typeCode);
	}

	/**
	 * 得到类影射的列表
	 * 
	 * @return
	 */
	public /* static*/ List<Class> getClassMapping() {
		return classMapping;
	}

	/**
	 * 添加一个处理类
	 * 
	 * @param clazz
	 */
	public /*static*/ void registerActionClass(Class clazz) {
		classMapping.add(clazz);
		initRegisterClass();
	}

	
	/**
	 * 获得函数对应的存储比例。
	 * 如果返回是null，则不存在；
	 * 返回=0，表示不限制；
	 * 返回>0，表示n次存储一次
	 * 
	 * @param method
	 * @return
	 *
	 * @author lipeilin
	 * @2011-2-22 下午01:36:48
	 */
	public /*static*/ Integer getShareRatio(Method method){
		return shareMethod.get(method);
	}

}
